/**
 * @fileOverview
 */

Karamu = Karamu || {};
Karamu.Controllers = Karamu.Controllers || {};

/**
 * Groups are displayed as categories in desktop view; as tabs in dashboard view. Tabs are sub-divided into columns, and
 * gadgets are stacked in the columns.
 *
 * @class
 * @requires jQuery, underscore.js, karamu.js
 * @param {Object} context the top-level controller object, e.g karamu
 */
Karamu.Controllers.Gadget = function(context){
    this.context = context;

    /**
     * @param {(Object|string)} element a jQuery object or jQuery selector for a single object to render into
     * @param {Object} gadget
     * @param {string} gadget.id must be unique to this view, within this group and across all groups
     * @param {string} gadget.title anything goes
     * @param {number} gadget.column
     * @param {string} gadget.height
     * @public
     */
    this.render = function(element, gadgetData) {
        this.element = $(element);

        var gadget = this.context.tmpl('dashboard-gadget', {
            id: 'gadget-' + gadgetData.id,
            title: gadgetData.title
        });
        gadget.appendTo(this.element);

        if (Modernizr.draganddrop) {
            gadget.attr('draggable', true).on({
                dragstart: this.dragstart,
                dragend: this.dragend
            }, this);
        }

        // enable drag-n-drop in IE
        if (gadget[0].dragDrop) {
            gadget.on({
                mousemove: this.mousemove
            }, this);
        }

        $('.close', gadget).on({
            click: this.removeElement
        }, this);

        var shindigGadget = shindig.container.createGadget({
            specUrl: gadgetData.url,
            title: gadgetData.title,
            height: gadgetData.height,
            width: '100%',
            scrolling: 'yes'
        });
        shindig.container.addGadget(shindigGadget);
        shindigGadget.render($('.gadget-body', gadget)[0]);
    };

    /**
     * @param {(Object|string)} element a jQuery object or jQuery selector for a single object to rerender into
     * @param {(Object|string)} element a jQuery object or jQuery selector for a single object containing a gadget
     * @public
     */
    this.rerender = function(element, gadget) {
        var element = $(element),
            gadget = $(gadget),
            shindigGadget = shindig.container.getGadget($('iframe', gadget).attr('id').replace('remote_iframe_', ''));

        // Move the gadget container, losing the rendered gadget in the process
        element.append(gadget);

        // Re-add and re-render the gadget
        shindig.container.addGadget(shindigGadget);
        shindigGadget.render($('.gadget-body', gadget)[0]);
    };

    /**
     * @param {?Object} e event object
     * @public
     */
    this.removeElement = function(e) {
        e.preventDefault();
        var el = $($(e.currentTarget).parents(e.data.context.controllers.catalog.options.gadgetSelector)),
            gadget = {
                id: el.attr('id').substr('gadget-'.length),
                column: $(el.parents(e.data.context.controllers.catalog.options.dropzoneSelector)).attr('data-column')
            },
            groupId = el.parents('.tab-pane').attr('id').substr('tab-pane-'.length);

        // Remove it from the interface
        el.remove();

        // Update the model
        $(e.data.context.models[e.data.context.view]).trigger('remove-gadget', [gadget, groupId]);
    };

    /**
     * @param {?Object} e event object
     * @public
     */
    this.mousemove = function(e) {
        var target = e.target;
        if (window.event.button === 1) {
            target.dragDrop();
        }
    };

    /**
     * @param {?Object} e event object
     * @public
     */
    this.dragstart = function(e) {
        $(e.data.context.controllers.catalog.options.dropzoneSelector).addClass('glow');
        $(e.currentTarget).css('opacity', 0.5);
        $(e.currentTarget).addClass('dragstart');
        e.originalEvent.dataTransfer.effectAllowed = 'copyMove';
        e.originalEvent.dataTransfer.setData('Text', JSON.stringify({id: $(e.currentTarget).attr('id').substr('gadget-'.length)}));
    };

    /**
     * @param {?Object} e event object
     * @public
     */
    this.dragend = function(e) {
        $(e.data.context.controllers.catalog.options.dropzoneSelector).removeClass('glow');
        $(e.currentTarget).css('opacity', 1);
        $(e.currentTarget).removeClass('dragstart');
    };

    /**
     * @param {Object} e event object
     * @param {Object} e.data the top-level controller object, e.g karamu
     * @param {Object} gadget a plain object
     * @param {string} groupId exactly what it sounds like
     * @public
     */
    this.add = function(e, gadget, groupId){
        for (var a = 0, b = e.data.models[e.data.view].groups.length; a < b; a++) {
            if (e.data.models[e.data.view].groups[a].id === groupId) {
                e.data.models[e.data.view].groups[a].gadgets.push(gadget);
                e.data.models[e.data.view]._group.gadgets
                e.data.models[e.data.view].groups[a].gadgets = e.data.controllers.group.sort(e.data.models[e.data.view].groups[a].gadgets, gadget.column, e.data);
                if (console && console.log) console.log('Gadget "' + gadget.title + '" (' + gadget.id + ') added to group (' + groupId + ').');
                $(e.data.models[e.data.view]).trigger('change-group', groupId);
            }
        }
    };

    /**
     * @param {Object} e event object
     * @param {Object} e.data the top-level controller object, e.g karamu
     * @param {Object} gadget a plain object
     * @param {string} groupId exactly what it sounds like
     * @public
     */
    this.change = function(e, gadgetId, gadgetData, groupId){
        for (var a = 0, b = e.data.models[e.data.view].groups.length; a < b; a++) {
            if (e.data.models[e.data.view].groups[a].id === groupId) {
                for (var c = 0, d = e.data.models[e.data.view].groups[a].gadgets.length; c < d; c++) {
                    if (e.data.models[e.data.view].groups[a].gadgets[c].id === gadgetId) {
                        if (gadgetData) {
                            for (f in gadgetData) {
                                e.data.models[e.data.view].groups[a].gadgets[c][f] = gadgetData[f];
                            }
                        }
                        e.data.models[e.data.view].groups[a].gadgets = e.data.controllers.group.sort(e.data.models[e.data.view].groups[a].gadgets, e.data.models[e.data.view].groups[a].gadgets[c].column, e.data);
                        if (console && console.log) console.log('Gadget (' + gadgetId + ') changed within group (' + groupId + ').');
                        $(e.data.models[e.data.view]).trigger('change-group', groupId);
                    }
                }
            }
        }
    };

    /**
     * @param {Object} e event object
     * @param {Object} e.data the top-level controller object, e.g karamu
     * @param {Object} gadgetId exactly what it sounds like
     * @param {string} groupId exactly what it sounds like
     * @public
     */
    this.remove = function(e, gadget, groupId) {
        for (var a = 0, b = e.data.models[e.data.view].groups.length; a < b; a++) {
            if (e.data.models[e.data.view].groups[a].id === groupId) {
                for (var c = 0, d = e.data.models[e.data.view].groups[a].gadgets.length; c < d; c++) {
                    if (e.data.models[e.data.view].groups[a].gadgets[c].id === gadget.id) {
                        e.data.models[e.data.view].groups[a].gadgets.splice(c, 1);
                        e.data.models[e.data.view].groups[a].gadgets = e.data.controllers.group.sort(e.data.models[e.data.view].groups[a].gadgets, gadget.column, e.data);
                        if (console && console.log) console.log('Gadget "' + gadget.title + '" (' + gadget.id + ') removed from group (' + groupId + ').');
                        $(e.data.models[e.data.view]).trigger('change-group', groupId);
                        d--;
                    }
                }
            }
        }
    };

};